Project 2 - Shiny App

Data Processing

# Load libraries needed
library(tidyverse)
library(lubridate)
License_Application <- read_csv("data/License_Applications.csv")
Warning: One or more parsing issues, see `problems()` for details
Rows: 420857 Columns: 25
── Column specification ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr  (21): Application ID, License Number, License Type, Application or Renewal, Business Name, Status, Start Date, End Date, Temp Op Letter Expiration, License ...
dbl   (2): Longitude, Latitude
lgl   (1): Active Vehicles
date  (1): Temp Op Letter Issued

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
dim(License_Application);names(License_Application)
[1] 420857     25
 [1] "Application ID"            "License Number"            "License Type"              "Application or Renewal"    "Business Name"            
 [6] "Status"                    "Start Date"                "End Date"                  "Temp Op Letter Issued"     "Temp Op Letter Expiration"
[11] "License Category"          "Application Category"      "Building Number"           "Street"                    "Street 2"                 
[16] "Unit Type"                 "Unit"                      "Description"               "City"                      "State"                    
[21] "Zip"                       "Contact Phone"             "Longitude"                 "Latitude"                  "Active Vehicles"          
License_App <- License_Application %>% filter(State == "NY") %>%
  mutate(Start_date = mdy(`Start Date`), End_date = mdy(`End Date`), City = tolower(City)) %>%
  dplyr::select(Start_date, End_date, `Application ID`, `License Number`, `License Type`,
                `Application or Renewal`,`Business Name`,Status,`License Category`,`Application Category`,`Building Number`,Street,City,State,Zip,Longitude,Latitude) %>% filter(Start_date >= as.Date("2017-01-01")) %>%
  arrange(Start_date) 

Five boroughs in new york are Brooklyn, Bronx, Manhattan,Queens, State Island. Queens indicated as “queens village” or “queens vlg”

NYC_License <- License_App %>% filter(City %in% c("bronx","brooklyn","new york",
                                                  "staten island", "manhattan", "queens village", "queens vlg"))

#Category count by month
License_by_month <- NYC_License %>% group_by(month = floor_date(Start_date,"month"),`Application or Renewal`,`License Category`) %>% summarise(cnt = n()) %>% 
  arrange(month)
`summarise()` has grouped output by 'month', 'Application or Renewal'. You can override using the `.groups` argument.
#Category_cnt of License Application
Category_cnt <- NYC_License %>% group_by(year = floor_date(Start_date,"year"),`Application or Renewal`,`License Category`) %>% summarise(cnt = n()) %>% 
  arrange(year, desc(cnt))
`summarise()` has grouped output by 'year', 'Application or Renewal'. You can override using the `.groups` argument.
#total_app_by_year <- License_App %>% group_by(year = floor_date(Start_date,"year"),`Application or Renewal`) %>% summarise(cnt = n()) %>% 
#  arrange(year)
#total_app


total_app_by_month <- 
 License_App %>% group_by(month = floor_date(Start_date,"month"),`Application or Renewal`) %>% summarise(cnt = n()) %>% 
  arrange(month)
`summarise()` has grouped output by 'month'. You can override using the `.groups` argument.
ggplot(total_app_by_month, aes(x = month, y = cnt)) +
  geom_line(aes(color = `Application or Renewal`)) +
  labs(y = "Number of License renewed and applied in month") +
  scale_x_date(breaks = "4 month") +
  theme(axis.text.x = element_text(angle = 90, vjust = 0.5)) 

Implement covid data

Covid_19_raw <- read_csv("data/COVID-19.csv")
Rows: 718 Columns: 62
── Column specification ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr  (1): DATE_OF_INTEREST
dbl (61): CASE_COUNT, probable_case_count, HOSPITALIZED_COUNT, DEATH_COUNT, DEATH_COUNT_PROBABLE, CASE_COUNT_7DAY_AVG, all_case_count_7day_avg, HOSP_COUNT_7DAY_A...

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
dim(Covid_19_raw);names(Covid_19_raw)
[1] 718  62
 [1] "DATE_OF_INTEREST"               "CASE_COUNT"                     "probable_case_count"            "HOSPITALIZED_COUNT"            
 [5] "DEATH_COUNT"                    "DEATH_COUNT_PROBABLE"           "CASE_COUNT_7DAY_AVG"            "all_case_count_7day_avg"       
 [9] "HOSP_COUNT_7DAY_AVG"            "DEATH_COUNT_7DAY_AVG"           "all_death_count_7day_avg"       "BX_CASE_COUNT"                 
[13] "bx_probable_case_count"         "BX_HOSPITALIZED_COUNT"          "BX_DEATH_COUNT"                 "bx_probable_death_count"       
[17] "BX_CASE_COUNT_7DAY_AVG"         "bx_all_case_count_7day_avg"     "BX_HOSPITALIZED_COUNT_7DAY_AVG" "BX_DEATH_COUNT_7DAY_AVG"       
[21] "bx_all_death_count_7day_avg"    "BK_CASE_COUNT"                  "bk_probable_case_count"         "BK_HOSPITALIZED_COUNT"         
[25] "BK_DEATH_COUNT"                 "bk_probable_death_count"        "BK_CASE_COUNT_7DAY_AVG"         "bk_all_case_count_7day_avg"    
[29] "BK_HOSPITALIZED_COUNT_7DAY_AVG" "BK_DEATH_COUNT_7DAY_AVG"        "bk_all_death_count_7day_avg"    "MN_CASE_COUNT"                 
[33] "mn_probable_case_count"         "MN_HOSPITALIZED_COUNT"          "MN_DEATH_COUNT"                 "mn_probable_death_count"       
[37] "MN_CASE_COUNT_7DAY_AVG"         "mn_all_case_count_7day_avg"     "MN_HOSPITALIZED_COUNT_7DAY_AVG" "MN_DEATH_COUNT_7DAY_AVG"       
[41] "mn_all_death_count_7day_avg"    "QN_CASE_COUNT"                  "qn_probable_case_count"         "QN_HOSPITALIZED_COUNT"         
[45] "QN_DEATH_COUNT"                 "qn_probable_death_count"        "QN_CASE_COUNT_7DAY_AVG"         "qn_all_case_count_7day_avg"    
[49] "QN_HOSPITALIZED_COUNT_7DAY_AVG" "QN_DEATH_COUNT_7DAY_AVG"        "qn_all_death_count_7day_avg"    "SI_CASE_COUNT"                 
[53] "si_probable_case_count"         "SI_HOSPITALIZED_COUNT"          "SI_DEATH_COUNT"                 "si_probable_death_count"       
[57] "SI_CASE_COUNT_7DAY_AVG"         "si_all_case_count_7day_avg"     "SI_HOSPITALIZED_COUNT_7DAY_AVG" "SI_DEATH_COUNT_7DAY_AVG"       
[61] "si_all_death_count_7day_avg"    "INCOMPLETE"                    
Covid_19 <- Covid_19_raw %>% mutate(Date = mdy(DATE_OF_INTEREST), .before = DATE_OF_INTEREST) %>%
  dplyr::select(Date, CASE_COUNT,probable_case_count, HOSPITALIZED_COUNT,DEATH_COUNT,
                DEATH_COUNT_PROBABLE,CASE_COUNT_7DAY_AVG,all_case_count_7day_avg,
                HOSP_COUNT_7DAY_AVG,DEATH_COUNT_7DAY_AVG,all_death_count_7day_avg)
  

Impact by covid ? How covid 19 affect application?

Join two tables

#covid 19 count by month, case count and death count,Date, CASE_COUNT,probable_case_count, HOSPITALIZED_COUNT,DEATH_COUNT,DEATH_COUNT_PROBABLE
Covid_by_month <- Covid_19 %>% group_by(month = floor_date(Date,"month")) %>% 
  summarise(monthly_case_count = sum(CASE_COUNT), monthly_death = sum(DEATH_COUNT), monthly_hospitalized = sum(HOSPITALIZED_COUNT),
            monthly_case_probable = sum(probable_case_count), monthly_death_probable = sum(DEATH_COUNT_PROBABLE)) %>% 
  arrange(desc(month))

Category_by_month <- NYC_License %>%
  group_by(month = floor_date(Start_date,"month"),
           `Application or Renewal`,`License Category`) %>%
  summarise(License_cnt = n()) %>% 
  arrange(month)
`summarise()` has grouped output by 'month', 'Application or Renewal'. You can override using the `.groups` argument.
Month_Application_Covid <- Category_by_month %>%
  inner_join(Covid_by_month, by = c("month" = "month"))

1.covid cases vs total applications 2.covid cases vs category applications

if (!require("plotly")) install.packages("plotly")
if (!require("viridis")) install.packages("viridis")
if (!require("hrbrthemes")) install.packages("hrbrthemes")
library(plotly)
library(viridis)
library(hrbrthemes)

data %>% arrange(desc(License_cnt))


#covid cases vs category applications
#The dataset is provided in the gapminder library
#data <- Month_Application_Covid %>% filter(`Application or Renewal` == "Application", `License Category` %in% c("Home Improvement Contractor"))
#p <- data %>% 
#  mutate(text = paste("Date:",month,"\nCovid_19 cases:",monthly_case_count,"\nApplications:",License_cnt,"\nLicense Category:",`License Category`, sep = "")) %>%
#  ggplot(aes(x=month,y=monthly_case_count,size = License_cnt, color = `License Category`,text = text))+
#  geom_point(alpha=0.7) +
#  geom_line(aes(y = monthly_case_count)) +
#  scale_size(range = c(1.4, 19), name="Population (M)") +
#  scale_color_viridis(discrete=TRUE, guide=FALSE) +
#  theme_ipsum() +
#  theme(legend.position="none")

#pp <- ggplotly(p, tooltip="text")
# pp

#covid cases vs total applications
data2 <- Month_Application_Covid %>% filter(`Application or Renewal` == "Application") %>% 
  group_by(month) %>%
  summarise(applications = sum(License_cnt), monthly_case_count=mean(monthly_case_count))
data2



p2 <- data2 %>% 
  mutate(text = paste("Date:",month,"\nCovid_19 cases:",monthly_case_count,"\nApplications:",applications, sep = "")) %>%
  ggplot(aes(x=month,y=monthly_case_count,size = applications, color = "lightgreen",text = text))+
  geom_point(alpha=0.7) +
  geom_line(aes(y = monthly_case_count)) +
  scale_size(range = c(1.4, 19), name="Population (M)") +
  scale_color_viridis(discrete=TRUE, guide=FALSE) +
  theme_ipsum() +
  theme(legend.position="none")

pp2 <- ggplotly(p2, tooltip="text")
pp2
NA
NA

App Template

if (!require("shiny")) install.packages("shiny")
library(shiny)

data <- Month_Application_Covid %>% filter(`Application or Renewal` == "Application") %>% 
  mutate(text = paste("Date:",month,"\nCovid_19 cases:",monthly_case_count,"\nApplications:",License_cnt,"\nLicense Category:",`License Category`, sep = "")) %>%
  

var <- unique(License_by_month$`License Category`)
Error in Month_Application_Covid %>% filter(`Application or Renewal` ==  : 
  could not find function "%>%<-"
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQojIFByb2plY3QgMiAtIFNoaW55IEFwcAoKRGF0YSBQcm9jZXNzaW5nCmBgYHtyLCBlY2hvID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZSA9IEZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQod2FybmluZyA9IEZBTFNFLCBlY2hvID0gVFJVRSkgCmBgYAoKYGBge3J9CiMgTG9hZCBsaWJyYXJpZXMgbmVlZGVkCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGx1YnJpZGF0ZSkKYGBgCgpgYGB7cn0KTGljZW5zZV9BcHBsaWNhdGlvbiA8LSByZWFkX2NzdigiZGF0YS9MaWNlbnNlX0FwcGxpY2F0aW9ucy5jc3YiKQpkaW0oTGljZW5zZV9BcHBsaWNhdGlvbik7bmFtZXMoTGljZW5zZV9BcHBsaWNhdGlvbikKCkxpY2Vuc2VfQXBwIDwtIExpY2Vuc2VfQXBwbGljYXRpb24gJT4lIGZpbHRlcihTdGF0ZSA9PSAiTlkiKSAlPiUKICBtdXRhdGUoU3RhcnRfZGF0ZSA9IG1keShgU3RhcnQgRGF0ZWApLCBFbmRfZGF0ZSA9IG1keShgRW5kIERhdGVgKSwgQ2l0eSA9IHRvbG93ZXIoQ2l0eSkpICU+JQogIGRwbHlyOjpzZWxlY3QoU3RhcnRfZGF0ZSwgRW5kX2RhdGUsIGBBcHBsaWNhdGlvbiBJRGAsIGBMaWNlbnNlIE51bWJlcmAsIGBMaWNlbnNlIFR5cGVgLAogICAgICAgICAgICAgICAgYEFwcGxpY2F0aW9uIG9yIFJlbmV3YWxgLGBCdXNpbmVzcyBOYW1lYCxTdGF0dXMsYExpY2Vuc2UgQ2F0ZWdvcnlgLGBBcHBsaWNhdGlvbiBDYXRlZ29yeWAsYEJ1aWxkaW5nIE51bWJlcmAsU3RyZWV0LENpdHksU3RhdGUsWmlwLExvbmdpdHVkZSxMYXRpdHVkZSkgJT4lIGZpbHRlcihTdGFydF9kYXRlID49IGFzLkRhdGUoIjIwMTctMDEtMDEiKSkgJT4lCiAgYXJyYW5nZShTdGFydF9kYXRlKSAKYGBgCkZpdmUgYm9yb3VnaHMgaW4gbmV3IHlvcmsgYXJlIEJyb29rbHluLCBCcm9ueCwgTWFuaGF0dGFuLFF1ZWVucywgU3RhdGUgSXNsYW5kLgpRdWVlbnMgaW5kaWNhdGVkIGFzICJxdWVlbnMgdmlsbGFnZSIgb3IgInF1ZWVucyB2bGciIAoKYGBge3J9Ck5ZQ19MaWNlbnNlIDwtIExpY2Vuc2VfQXBwICU+JSBmaWx0ZXIoQ2l0eSAlaW4lIGMoImJyb254IiwiYnJvb2tseW4iLCJuZXcgeW9yayIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInN0YXRlbiBpc2xhbmQiLCAibWFuaGF0dGFuIiwgInF1ZWVucyB2aWxsYWdlIiwgInF1ZWVucyB2bGciKSkKCiNDYXRlZ29yeSBjb3VudCBieSBtb250aApMaWNlbnNlX2J5X21vbnRoIDwtIE5ZQ19MaWNlbnNlICU+JSBncm91cF9ieShtb250aCA9IGZsb29yX2RhdGUoU3RhcnRfZGF0ZSwibW9udGgiKSxgQXBwbGljYXRpb24gb3IgUmVuZXdhbGAsYExpY2Vuc2UgQ2F0ZWdvcnlgKSAlPiUgc3VtbWFyaXNlKGNudCA9IG4oKSkgJT4lIAogIGFycmFuZ2UobW9udGgpCgoKI0NhdGVnb3J5X2NudCBvZiBMaWNlbnNlIEFwcGxpY2F0aW9uCkNhdGVnb3J5X2NudCA8LSBOWUNfTGljZW5zZSAlPiUgZ3JvdXBfYnkoeWVhciA9IGZsb29yX2RhdGUoU3RhcnRfZGF0ZSwieWVhciIpLGBBcHBsaWNhdGlvbiBvciBSZW5ld2FsYCxgTGljZW5zZSBDYXRlZ29yeWApICU+JSBzdW1tYXJpc2UoY250ID0gbigpKSAlPiUgCiAgYXJyYW5nZSh5ZWFyLCBkZXNjKGNudCkpCgojdG90YWxfYXBwX2J5X3llYXIgPC0gTGljZW5zZV9BcHAgJT4lIGdyb3VwX2J5KHllYXIgPSBmbG9vcl9kYXRlKFN0YXJ0X2RhdGUsInllYXIiKSxgQXBwbGljYXRpb24gb3IgUmVuZXdhbGApICU+JSBzdW1tYXJpc2UoY250ID0gbigpKSAlPiUgCiMgIGFycmFuZ2UoeWVhcikKI3RvdGFsX2FwcAoKCnRvdGFsX2FwcF9ieV9tb250aCA8LSAKIExpY2Vuc2VfQXBwICU+JSBncm91cF9ieShtb250aCA9IGZsb29yX2RhdGUoU3RhcnRfZGF0ZSwibW9udGgiKSxgQXBwbGljYXRpb24gb3IgUmVuZXdhbGApICU+JSBzdW1tYXJpc2UoY250ID0gbigpKSAlPiUgCiAgYXJyYW5nZShtb250aCkKCmdncGxvdCh0b3RhbF9hcHBfYnlfbW9udGgsIGFlcyh4ID0gbW9udGgsIHkgPSBjbnQpKSArCiAgZ2VvbV9saW5lKGFlcyhjb2xvciA9IGBBcHBsaWNhdGlvbiBvciBSZW5ld2FsYCkpICsKICBsYWJzKHkgPSAiTnVtYmVyIG9mIExpY2Vuc2UgcmVuZXdlZCBhbmQgYXBwbGllZCBpbiBtb250aCIpICsKICBzY2FsZV94X2RhdGUoYnJlYWtzID0gIjQgbW9udGgiKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgdmp1c3QgPSAwLjUpKSAKYGBgCgoKCiMgSW1wbGVtZW50IGNvdmlkIGRhdGEKYGBge3J9CkNvdmlkXzE5X3JhdyA8LSByZWFkX2NzdigiZGF0YS9DT1ZJRC0xOS5jc3YiKQpkaW0oQ292aWRfMTlfcmF3KTtuYW1lcyhDb3ZpZF8xOV9yYXcpCgpDb3ZpZF8xOSA8LSBDb3ZpZF8xOV9yYXcgJT4lIG11dGF0ZShEYXRlID0gbWR5KERBVEVfT0ZfSU5URVJFU1QpLCAuYmVmb3JlID0gREFURV9PRl9JTlRFUkVTVCkgJT4lCiAgZHBseXI6OnNlbGVjdChEYXRlLCBDQVNFX0NPVU5ULHByb2JhYmxlX2Nhc2VfY291bnQsIEhPU1BJVEFMSVpFRF9DT1VOVCxERUFUSF9DT1VOVCwKICAgICAgICAgICAgICAgIERFQVRIX0NPVU5UX1BST0JBQkxFLENBU0VfQ09VTlRfN0RBWV9BVkcsYWxsX2Nhc2VfY291bnRfN2RheV9hdmcsCiAgICAgICAgICAgICAgICBIT1NQX0NPVU5UXzdEQVlfQVZHLERFQVRIX0NPVU5UXzdEQVlfQVZHLGFsbF9kZWF0aF9jb3VudF83ZGF5X2F2ZykKICAKYGBgCgojIyMgSW1wYWN0IGJ5IGNvdmlkID8gSG93IGNvdmlkIDE5IGFmZmVjdCBhcHBsaWNhdGlvbj8gCkpvaW4gdHdvIHRhYmxlcwoKYGBge3J9CiNjb3ZpZCAxOSBjb3VudCBieSBtb250aCwgY2FzZSBjb3VudCBhbmQgZGVhdGggY291bnQsRGF0ZSwgQ0FTRV9DT1VOVCxwcm9iYWJsZV9jYXNlX2NvdW50LCBIT1NQSVRBTElaRURfQ09VTlQsREVBVEhfQ09VTlQsREVBVEhfQ09VTlRfUFJPQkFCTEUKQ292aWRfYnlfbW9udGggPC0gQ292aWRfMTkgJT4lIGdyb3VwX2J5KG1vbnRoID0gZmxvb3JfZGF0ZShEYXRlLCJtb250aCIpKSAlPiUgCiAgc3VtbWFyaXNlKG1vbnRobHlfY2FzZV9jb3VudCA9IHN1bShDQVNFX0NPVU5UKSwgbW9udGhseV9kZWF0aCA9IHN1bShERUFUSF9DT1VOVCksIG1vbnRobHlfaG9zcGl0YWxpemVkID0gc3VtKEhPU1BJVEFMSVpFRF9DT1VOVCksCiAgICAgICAgICAgIG1vbnRobHlfY2FzZV9wcm9iYWJsZSA9IHN1bShwcm9iYWJsZV9jYXNlX2NvdW50KSwgbW9udGhseV9kZWF0aF9wcm9iYWJsZSA9IHN1bShERUFUSF9DT1VOVF9QUk9CQUJMRSkpICU+JSAKICBhcnJhbmdlKGRlc2MobW9udGgpKQoKQ2F0ZWdvcnlfYnlfbW9udGggPC0gTllDX0xpY2Vuc2UgJT4lCiAgZ3JvdXBfYnkobW9udGggPSBmbG9vcl9kYXRlKFN0YXJ0X2RhdGUsIm1vbnRoIiksCiAgICAgICAgICAgYEFwcGxpY2F0aW9uIG9yIFJlbmV3YWxgLGBMaWNlbnNlIENhdGVnb3J5YCkgJT4lCiAgc3VtbWFyaXNlKExpY2Vuc2VfY250ID0gbigpKSAlPiUgCiAgYXJyYW5nZShtb250aCkKCgpNb250aF9BcHBsaWNhdGlvbl9Db3ZpZCA8LSBDYXRlZ29yeV9ieV9tb250aCAlPiUKICBpbm5lcl9qb2luKENvdmlkX2J5X21vbnRoLCBieSA9IGMoIm1vbnRoIiA9ICJtb250aCIpKQoKYGBgCgoxLmNvdmlkIGNhc2VzIHZzIHRvdGFsIGFwcGxpY2F0aW9ucwoyLmNvdmlkIGNhc2VzIHZzIGNhdGVnb3J5IGFwcGxpY2F0aW9ucwpgYGB7cn0KaWYgKCFyZXF1aXJlKCJwbG90bHkiKSkgaW5zdGFsbC5wYWNrYWdlcygicGxvdGx5IikKaWYgKCFyZXF1aXJlKCJ2aXJpZGlzIikpIGluc3RhbGwucGFja2FnZXMoInZpcmlkaXMiKQppZiAoIXJlcXVpcmUoImhyYnJ0aGVtZXMiKSkgaW5zdGFsbC5wYWNrYWdlcygiaHJicnRoZW1lcyIpCmxpYnJhcnkocGxvdGx5KQpsaWJyYXJ5KHZpcmlkaXMpCmxpYnJhcnkoaHJicnRoZW1lcykKCmRhdGEgJT4lIGFycmFuZ2UoZGVzYyhMaWNlbnNlX2NudCkpCgoKI2NvdmlkIGNhc2VzIHZzIGNhdGVnb3J5IGFwcGxpY2F0aW9ucwojVGhlIGRhdGFzZXQgaXMgcHJvdmlkZWQgaW4gdGhlIGdhcG1pbmRlciBsaWJyYXJ5CiNkYXRhIDwtIE1vbnRoX0FwcGxpY2F0aW9uX0NvdmlkICU+JSBmaWx0ZXIoYEFwcGxpY2F0aW9uIG9yIFJlbmV3YWxgID09ICJBcHBsaWNhdGlvbiIsIGBMaWNlbnNlIENhdGVnb3J5YCAlaW4lIGMoIkhvbWUgSW1wcm92ZW1lbnQgQ29udHJhY3RvciIpKQojcCA8LSBkYXRhICU+JSAKIyAgbXV0YXRlKHRleHQgPSBwYXN0ZSgiRGF0ZToiLG1vbnRoLCJcbkNvdmlkXzE5IGNhc2VzOiIsbW9udGhseV9jYXNlX2NvdW50LCJcbkFwcGxpY2F0aW9uczoiLExpY2Vuc2VfY250LCJcbkxpY2Vuc2UgQ2F0ZWdvcnk6IixgTGljZW5zZSBDYXRlZ29yeWAsIHNlcCA9ICIiKSkgJT4lCiMgIGdncGxvdChhZXMoeD1tb250aCx5PW1vbnRobHlfY2FzZV9jb3VudCxzaXplID0gTGljZW5zZV9jbnQsIGNvbG9yID0gYExpY2Vuc2UgQ2F0ZWdvcnlgLHRleHQgPSB0ZXh0KSkrCiMgIGdlb21fcG9pbnQoYWxwaGE9MC43KSArCiMgIGdlb21fbGluZShhZXMoeSA9IG1vbnRobHlfY2FzZV9jb3VudCkpICsKIyAgc2NhbGVfc2l6ZShyYW5nZSA9IGMoMS40LCAxOSksIG5hbWU9IlBvcHVsYXRpb24gKE0pIikgKwojICBzY2FsZV9jb2xvcl92aXJpZGlzKGRpc2NyZXRlPVRSVUUsIGd1aWRlPUZBTFNFKSArCiMgIHRoZW1lX2lwc3VtKCkgKwojICB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKQoKI3BwIDwtIGdncGxvdGx5KHAsIHRvb2x0aXA9InRleHQiKQojIHBwCgojY292aWQgY2FzZXMgdnMgdG90YWwgYXBwbGljYXRpb25zCmRhdGEyIDwtIE1vbnRoX0FwcGxpY2F0aW9uX0NvdmlkICU+JSBmaWx0ZXIoYEFwcGxpY2F0aW9uIG9yIFJlbmV3YWxgID09ICJBcHBsaWNhdGlvbiIpICU+JSAKICBncm91cF9ieShtb250aCkgJT4lCiAgc3VtbWFyaXNlKGFwcGxpY2F0aW9ucyA9IHN1bShMaWNlbnNlX2NudCksIG1vbnRobHlfY2FzZV9jb3VudD1tZWFuKG1vbnRobHlfY2FzZV9jb3VudCkpCmRhdGEyCgoKCnAyIDwtIGRhdGEyICU+JSAKICBtdXRhdGUodGV4dCA9IHBhc3RlKCJEYXRlOiIsbW9udGgsIlxuQ292aWRfMTkgY2FzZXM6Iixtb250aGx5X2Nhc2VfY291bnQsIlxuQXBwbGljYXRpb25zOiIsYXBwbGljYXRpb25zLCBzZXAgPSAiIikpICU+JQogIGdncGxvdChhZXMoeD1tb250aCx5PW1vbnRobHlfY2FzZV9jb3VudCxzaXplID0gYXBwbGljYXRpb25zLCBjb2xvciA9ICJsaWdodGdyZWVuIix0ZXh0ID0gdGV4dCkpKwogIGdlb21fcG9pbnQoYWxwaGE9MC43KSArCiAgZ2VvbV9saW5lKGFlcyh5ID0gbW9udGhseV9jYXNlX2NvdW50KSkgKwogIHNjYWxlX3NpemUocmFuZ2UgPSBjKDEuNCwgMTkpLCBuYW1lPSJQb3B1bGF0aW9uIChNKSIpICsKICBzY2FsZV9jb2xvcl92aXJpZGlzKGRpc2NyZXRlPVRSVUUsIGd1aWRlPUZBTFNFKSArCiAgdGhlbWVfaXBzdW0oKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikKCnBwMiA8LSBnZ3Bsb3RseShwMiwgdG9vbHRpcD0idGV4dCIpCnBwMgoKCmBgYAoKCgojIEFwcCBUZW1wbGF0ZQpgYGB7cn0KaWYgKCFyZXF1aXJlKCJzaGlueSIpKSBpbnN0YWxsLnBhY2thZ2VzKCJzaGlueSIpCmxpYnJhcnkoc2hpbnkpCmBgYAoKYGBge3J9CgpkYXRhIDwtIE1vbnRoX0FwcGxpY2F0aW9uX0NvdmlkICU+JSBmaWx0ZXIoYEFwcGxpY2F0aW9uIG9yIFJlbmV3YWxgID09ICJBcHBsaWNhdGlvbiIpICU+JSAKICBtdXRhdGUodGV4dCA9IHBhc3RlKCJEYXRlOiIsbW9udGgsIlxuQ292aWRfMTkgY2FzZXM6Iixtb250aGx5X2Nhc2VfY291bnQsIlxuQXBwbGljYXRpb25zOiIsTGljZW5zZV9jbnQsIlxuTGljZW5zZSBDYXRlZ29yeToiLGBMaWNlbnNlIENhdGVnb3J5YCwgc2VwID0gIiIpKSAlPiUKICAKCnZhciA8LSB1bmlxdWUoTGljZW5zZV9ieV9tb250aCRgTGljZW5zZSBDYXRlZ29yeWApCgp5ciA8LSBjKCIyMDIyIiwiMjAyMSIsIjIwMjAiLCIyMDE5IiwiMjAxOCIsIjIwMTciKQoKc2hpbnlVSSA8LSBmbHVpZFBhZ2UoCiAgdGl0bGVQYW5lbCgiQXBwbGljYXRpb25zIG9mIERpZmZlcmVudCBMaWNlbnNlIENhdGVnb3J5IiksCiAgc2lkZWJhckxheW91dChwb3NpdGlvbiA9ICJsZWZ0IiwKICAgICAgICAgICAgICAgIAogIHNpZGViYXJQYW5lbCgKICAgIHNlbGVjdElucHV0KCJ5ZWFyIixsYWJlbCA9ICJTZWxlY3QgeWVhciIsIGNob2ljZXMgPSB5ciwgc2VsZWN0ZWQgPSAiMjAxNyIsIG11bHRpcGxlID0gRiksCiAgICBzZWxlY3RJbnB1dCgiY2F0ZWdvcnkiLCBsYWJlbD0gIlNlbGVjdCBhIExpY2Vuc2UgQ2F0ZWdvcnkiLCBjaG9pY2VzID0gdmFyLAogIHNlbGVjdGVkID0gIkVsZWN0cm9uaWNzIFN0b3JlIiwgbXVsdGlwbGUgPSBUKQogICAgICApLAogIG1haW5QYW5lbCgKICAgIHBsb3RPdXRwdXQoImhpc3QiKSwKICAgIHBsb3RPdXRwdXQoJ3Bsb3QnLGhvdmVyICA9ICJwbG90X2hvdmVyIiksCiAgICAgICAgdmVyYmF0aW1UZXh0T3V0cHV0KCJpbmZvIiksCiAgICBwbG90bHlPdXRwdXQoJ3Bsb3QxJykKCiAgICAgICAgICApCiAgKQopCiAgCiNzZXJ2ZXIuUgpzaGlueVNlcnZlcjwtIGZ1bmN0aW9uKGlucHV0LCBvdXRwdXQpIHsKICAKICBvdXRwdXQkaGlzdCA8LSByZW5kZXJQbG90KHsKICAgIAogIGdncGxvdChkYXRhID0gZmlsdGVyKENhdGVnb3J5X2NudCx5ZWFyKHllYXIpID09ICEhaW5wdXQkeWVhciApLGFlcyh4ID0gYExpY2Vuc2UgQ2F0ZWdvcnlgLCB5ID0gY250LCBmaWxsID0gYEFwcGxpY2F0aW9uIG9yIFJlbmV3YWxgKSkgKyAKICBnZW9tX2NvbCgpICsgCiAgbGFicyh5ID0gIk51bWJlciBvZiBBcHBsaWNhdGlvbnMgb3IgUmVuZXdhbHMgIiwKICAgICAgIHRpdGxlID0gIkFwcGxpY2F0aW9uIGFuZCBSZW5ld2FsIGZvciBMaWNlbnNlIENhdGVnb3J5IikgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIHNpemUgPSAxMCkpIAoKICAgIAogIH0pCiAgCiAgCiAgCiAgb3V0cHV0JHBsb3QgPC0gIHJlbmRlclBsb3QoewogICAgZ2dwbG90KGRhdGEgPSBmaWx0ZXIoTGljZW5zZV9ieV9tb250aCxgTGljZW5zZSBDYXRlZ29yeWAgPT0gISFpbnB1dCRjYXRlZ29yeSksYWVzKHggPSBtb250aCwgeSA9IGNudCxjb2xvciA9IGBBcHBsaWNhdGlvbiBvciBSZW5ld2FsYCkpICsKICAgIGdlb21fcG9pbnQoKSArCiAgICAgICAgICAgICBnZW9tX2xpbmUoKSArCiAgICBsYWJzKHRpdGxlID0gIkFwcGxpY2F0aW9ucyBhbmQgUmVuZXdhbHMgZm9yIExpY2Vuc2UgY2F0ZWdvcmllcyIsCiAgICAgICAgIHggPSAibW9udGgiLAogICAgICAgICB5ID0gIk51bWJlciBvZiBBcHBsaWNhdGlvbnMgb3IgUmVuZXdhbHMiKSArCiAgICBzY2FsZV94X2RhdGUoYnJlYWtzID0gIjQgbW9udGgiKSArCiAgICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCB2anVzdCA9IDAuNSkpCiAgfSkKICAKICAKICBvdXRwdXQkaW5mbyA8LSByZW5kZXJUZXh0KHsKICAgIGlucHV0JHBsb3RfaG92ZXIkeQogIH0pCiAgCiAgb3V0cHV0JHBsb3QxIDwtIHJlbmRlclBsb3RseSh7CiAgZ2dwbG90bHkoZ2dwbG90KGRhdGEgPSBmaWx0ZXIoZGF0YSxgTGljZW5zZSBDYXRlZ29yeWAgPT0gISFpbnB1dCRjYXRlZ29yeSksYWVzKHg9bW9udGgseT1tb250aGx5X2Nhc2VfY291bnQsc2l6ZSA9IExpY2Vuc2VfY250LCBjb2xvciA9IGBMaWNlbnNlIENhdGVnb3J5YCx0ZXh0ID0gdGV4dCkpKwogIGdlb21fcG9pbnQoYWxwaGE9MC43KSArCiAgZ2VvbV9saW5lKGFlcyh5ID0gbW9udGhseV9jYXNlX2NvdW50KSkgKwogIHNjYWxlX3NpemUocmFuZ2UgPSBjKDAuNSwgMTIpLCBuYW1lPSJBcHBsaWNhdGlvbnMiKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIiNFN0I4MDAiKSkgKwogIGxhYnModGl0bGUgPSAiQXBwbGljYXRpb25zIHVuZGVyIENvdmlkXzE5IiwKICAgICAgIHkgPSAiQ292aWRfMTkgTW9udGhseSBDYXNlIENvdW50IikgKwogIHRoZW1lX2lwc3VtKCkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpLCB0b29sdGlwID0gInRleHQiICkKCiAgfSkKICAKICAKICB9CnNoaW55QXBwKHVpID0gc2hpbnlVSSwgc2VydmVyID0gc2hpbnlTZXJ2ZXIpCgoKYGBgCgoK